﻿/*
 * Created by SharpDevelop.
 * User: Chris
 * Date: 5/7/2013
 * Time: 12:21 AM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Linq;

using Dither.Xna.Bindings.Project;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Internal.Templates;
using ICSharpCode.SharpDevelop.Project;
using Microsoft.Xna.Framework.Content.Pipeline;

namespace Dither.Xna.Bindings.Project
{
	/// <summary>
	/// Description of XnaContentProject.
	/// </summary>
	public class XnaContentProject : CompilableProject
	{	
		public const string DefaultTargetsFile = @"$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\$(XnaFrameworkVersion)\Microsoft.Xna.GameStudio.ContentPipeline.targets";

        public string ContentDirectory 
        {
            get {
                return GetProperty(this.ActiveConfiguration, this.ActivePlatform, "ContentRootDirectory");
            }
            set {
                SetProperty("ContentRootDirectory", value);
                this.Save();
            }
        }
		
		public override LanguageProperties LanguageProperties {
			get {
				return LanguageProperties.None;
			}
		}
		
		public override string Language {
			get {
				return XnaContentProjectBindings.LanguageName;
			}
		}
		
		public XnaContentProject(ProjectLoadInformation loadInformation)
			: base(loadInformation) 
		{
			Init();
		}
		
		public XnaContentProject(ProjectCreateInformation createInformation)
			: base(createInformation) 
		{
			Init();
			
			SetProperty("XnaFrameworkVersion", "v4.0");
			SetProperty("ContentRootDirectory", "Content");
			
			this.AddImport(DefaultTargetsFile, null);
		}
		
		void Init()
		{
			reparseReferencesSensitiveProperties.Add("XnaFrameworkVersion");
			reparseReferencesSensitiveProperties.Add("ContentRootDirectory");
		}
		
		protected override ProjectBehavior CreateDefaultBehavior()
		{
			return new XnaContentProjectBehavior(this, base.CreateDefaultBehavior());
		}
		
		public override void StartBuild(ProjectBuildOptions options, IBuildFeedbackSink feedbackSink)
		{
			feedbackSink.Done(true);
		}
		
		private IEnumerable<ContentProcessorDefinition> GetContentProcessorDefinitions(Assembly assembly)
		{
			foreach(Type type in assembly.GetTypes()) 
			{
				object[] contentProcessorAttributes = type.GetCustomAttributes(typeof(ContentProcessorAttribute), true);
				
		        if (contentProcessorAttributes.Length > 0)
		        {
		        	for (int i = 0; i < contentProcessorAttributes.Length; i++) 
		        	{
		        		ContentProcessorAttribute attribute = contentProcessorAttributes[i] as ContentProcessorAttribute;
		        		
		        		if (attribute != null)
		        		{
		        			yield return new ContentProcessorDefinition(attribute.DisplayName, type.ToString());
		        		}
		        	}
		        }
			}
		}
		
		private Dictionary<string, ContentProcessorDefinition> GetContentProcessorDefinitionDictionary(Assembly assembly)
		{
			IEnumerable<ContentProcessorDefinition> definitions = GetContentProcessorDefinitions(assembly);
			
			Dictionary<string, ContentProcessorDefinition> dictionary = new Dictionary<string, ContentProcessorDefinition>();
			
			foreach (var definition in definitions) {
				dictionary.Add(definition.Name, definition);
			}
			
			return dictionary;
		}
		
		private IEnumerable<string> GetLowerIEnumerableString(IEnumerable<string> strings)
		{			
			foreach (var item in strings) {
				yield return item.ToLower();
			}
		}
		
		private IEnumerable<ContentImporterDefiniton> GetContentImporterDefinitions(Assembly assembly, Dictionary<string, ContentProcessorDefinition> contentProcessors)
		{
			foreach(Type type in assembly.GetTypes()) 
			{
				object[] contentImporterAttributes = type.GetCustomAttributes(typeof(ContentImporterAttribute), true);
				
		        if (contentImporterAttributes.Length > 0)
		        {
		        	for (int i = 0; i < contentImporterAttributes.Length; i++) 
		        	{
		        		ContentImporterAttribute attribute = contentImporterAttributes[i] as ContentImporterAttribute;
		        		
		        		if (attribute != null)
		        		{
		        			ContentImporterDefiniton definition = new ContentImporterDefiniton();
		        			definition.DisplayName = attribute.DisplayName;
		        			definition.Name = type.ToString();
		        			definition.FileExtensions = GetLowerIEnumerableString(attribute.FileExtensions).ToArray<string>();
		        			definition.DefaultProcessor = contentProcessors[attribute.DefaultProcessor];
		        			
		        			yield return definition;
		        		}
		        	}
		        }
			}
		}
		
		private Dictionary<string, ContentImporterDefiniton> GetComponentImporterDefinitionsDictionary(Assembly assembly, Dictionary<string, ContentProcessorDefinition> contentProcessors)
		{
			IEnumerable<ContentImporterDefiniton> definitions = GetContentImporterDefinitions(assembly, contentProcessors);
			
			Dictionary<string, ContentImporterDefiniton> dictionary = new Dictionary<string, ContentImporterDefiniton>();
			
			foreach (ContentImporterDefiniton definition in definitions) {
				for (int i = 0; i < definition.FileExtensions.Length; i++) {
					dictionary.Add(definition.FileExtensions[i], definition);
				}
			}
			
			return dictionary;
		}
	}
	
	public class XnaContentProjectBehavior : ProjectBehavior
	{
		public XnaContentProjectBehavior(XnaContentProject project, ProjectBehavior next = null)
			: base(project, next) { }
		
		public override ItemType GetDefaultItemType(string fileName)
		{
			if (XnaContentFileName.IsContentFile(fileName)) {
				return ItemType.Compile;
			}
			
			return base.GetDefaultItemType(fileName);
		}
		
		public override ProjectItem CreateProjectItem(IProjectItemBackendStore item)
		{
            ProjectItem projectItem = null;
            switch (item.ItemType.ItemName)
            {
                case "Compile":
                    projectItem = new XnaContentFileProjectItem(item);
                    break;
                default:
                    projectItem = base.CreateProjectItem(item);
                    break;
            }

            return projectItem;
		}
	}
}
